package com.b511.swpu.cementbackend.util;

import com.b511.swpu.cementbackend.dto.output.ErrorOutputDto;
import com.b511.swpu.cementbackend.entity.CementBaseEntity;
import com.b511.swpu.cementbackend.entity.MetaField;
import com.b511.swpu.cementbackend.repository.MetaTableRepository;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

@Component
public class ValidateUtil {

    private Map<String, MetaField> rules;

    private final MetaTableRepository metaTableRepository;

    public ValidateUtil(MetaTableRepository metaTableRepository) {
        this.metaTableRepository = metaTableRepository;
    }

    public void setRules(Class table) {
        this.rules = getRule(table);
    }

    public ErrorOutputDto validate(CementBaseEntity o) {
        ErrorOutputDto errorOutputDto = new ErrorOutputDto();
        BeanWrapper wrapper = new BeanWrapperImpl(o);
        StringBuffer info = new StringBuffer();
        for (java.beans.PropertyDescriptor pd : wrapper.getPropertyDescriptors()) {
            String filedName = pd.getName();
            if (rules.containsKey(filedName)) {
                MetaField metaField = rules.get(filedName);
                Object value = wrapper.getPropertyValue(filedName);
                String regularExpression = metaField.getRegularExpression();
                String filedDescription = metaField.getFiledDescription();
                String description = null;
                if (null == value && metaField.isNotNull()) {
                    description = "空值异常";
                }
                if (null != value && StringUtils.hasText(regularExpression)
                        && !Pattern.matches(regularExpression, value.toString())) {
                    description = metaField.getDescription();
                }
                info = getErrorStringBuffer(info, filedDescription, description);
            }
        }
        setStatus(info.length() != 0, info.toString(), o, errorOutputDto);
        o.setIsCheck(true);
        return errorOutputDto;
    }

    private void setStatus(boolean isError, String info, CementBaseEntity o, ErrorOutputDto errorOutputDto) {
        o.setIsError(isError);
        o.setErrorInfo(info);
        errorOutputDto.setError(isError);
        errorOutputDto.setInfo(info);
    }

    private StringBuffer getErrorStringBuffer(StringBuffer info, String filedNameDescription, String description) {
        if (null != description) {
            if (info.length() != 0) {
                info.append(" , ");
            }
            info.append(filedNameDescription).append(" : ").append(description);
        }
        return info;
    }

    private Map<String, MetaField> getRule(Class table) {
        Map<String, MetaField> result = new HashMap<>();
        metaTableRepository.findByTableName(Help.humpToLine(table.getSimpleName()))
                .getMetaFields().forEach((metaField) -> {
            result.put(Help.lineToHump(metaField.getFiledName()), metaField);
        });
        return result;
    }

}
